home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 008a / perl40_2.zip / UTIL.C < prev    next >
C/C++ Source or Header  |  1991-11-28  |  37KB  |  1,856 lines

  1. /* $RCSfile: util.c,v $$Revision: 4.0.1.4 $$Date: 91/11/11 16:48:54 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    util.c,v $
  9.  * Revision 4.0.1.4  91/11/11  16:48:54  lwall
  10.  * patch19: study was busted by 4.018
  11.  * patch19: added little-endian pack/unpack options
  12.  *
  13.  * Revision 4.0.1.3  91/11/05  19:18:26  lwall
  14.  * patch11: safe malloc code now integrated into Perl's malloc when possible
  15.  * patch11: index("little", "longer string") could visit faraway places
  16.  * patch11: warn '-' x 10000 dumped core
  17.  * patch11: forked exec on non-existent program now issues a warning
  18.  *
  19.  * Revision 4.0.1.2  91/06/07  12:10:42  lwall
  20.  * patch4: new copyright notice
  21.  * patch4: made some allowances for "semi-standard" C
  22.  * patch4: index() could blow up searching for null string
  23.  * patch4: taintchecks could improperly modify parent in vfork()
  24.  * patch4: exec would close files even if you cleared close-on-exec flag
  25.  *
  26.  * Revision 4.0.1.1  91/04/12  09:19:25  lwall
  27.  * patch1: random cleanup in cpp namespace
  28.  *
  29.  * Revision 4.0  91/03/20  01:56:39  lwall
  30.  * 4.0 baseline.
  31.  *
  32.  */
  33. /*SUPPRESS 112*/
  34.  
  35.  
  36. #include "EXTERN.h"
  37. #include "perl.h"
  38.  
  39.  
  40. #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
  41. #include <signal.h>
  42. #endif
  43.  
  44.  
  45. #ifdef I_VFORK
  46. #  include <vfork.h>
  47. #endif
  48.  
  49.  
  50. #ifdef I_VARARGS
  51. #  include <varargs.h>
  52. #endif
  53.  
  54.  
  55. #ifdef I_FCNTL
  56. #  include <fcntl.h>
  57. #endif
  58. #ifdef I_SYS_FILE
  59. #  include <sys/file.h>
  60. #endif
  61.  
  62.  
  63. #define FLUSH
  64.  
  65.  
  66. #ifndef safemalloc
  67.  
  68.  
  69. static char nomem[] = "Out of memory!\n";
  70.  
  71.  
  72. /* paranoid version of malloc */
  73.  
  74.  
  75. #ifdef DEBUGGING
  76. static int an = 0;
  77. #endif
  78.  
  79.  
  80. /* NOTE:  Do not call the next three routines directly.  Use the macros
  81.  * in handy.h, so that we can easily redefine everything to do tracking of
  82.  * allocated hunks back to the original New to track down any memory leaks.
  83.  */
  84.  
  85.  
  86. char *
  87. safemalloc(size)
  88. #ifdef MSDOS
  89. unsigned long size;
  90. #else
  91. MEM_SIZE size;
  92. #endif /* MSDOS */
  93. {
  94.     char *ptr;
  95. #ifndef STANDARD_C
  96.     char *malloc();
  97. #endif /* ! STANDARD_C */
  98.  
  99.  
  100. #ifdef MSDOS
  101.     if (size > 0xffff) {
  102.         fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
  103.         exit(1);
  104.     }
  105. #endif /* MSDOS */
  106. #ifdef DEBUGGING
  107.     if ((long)size < 0)
  108.     fatal("panic: malloc");
  109. #endif
  110.     ptr = malloc(size?size:1);    /* malloc(0) is NASTY on our system */
  111. #ifdef DEBUGGING
  112. #  ifndef I286
  113.     if (debug & 128)
  114.     fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
  115. #  else
  116.     if (debug & 128)
  117.     fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
  118. #  endif
  119. #endif
  120.     if (ptr != Nullch)
  121.     return ptr;
  122.     else {
  123.     fputs(nomem,stderr) FLUSH;
  124.     exit(1);
  125.     }
  126.     /*NOTREACHED*/
  127. #ifdef lint
  128.     return ptr;
  129. #endif
  130. }
  131.  
  132.  
  133. /* paranoid version of realloc */
  134.  
  135.  
  136. char *
  137. saferealloc(where,size)
  138. char *where;
  139. #ifndef MSDOS
  140. MEM_SIZE size;
  141. #else
  142. unsigned long size;
  143. #endif /* MSDOS */
  144. {
  145.     char *ptr;
  146. #ifndef STANDARD_C
  147.     char *realloc();
  148. #endif /* ! STANDARD_C */
  149.  
  150.  
  151. #ifdef MSDOS
  152.     if (size > 0xffff) {
  153.         fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
  154.         exit(1);
  155.     }
  156. #endif /* MSDOS */
  157.     if (!where)
  158.     fatal("Null realloc");
  159. #ifdef DEBUGGING
  160.     if ((long)size < 0)
  161.     fatal("panic: realloc");
  162. #endif
  163.     ptr = realloc(where,size?size:1);    /* realloc(0) is NASTY on our system */
  164. #ifdef DEBUGGING
  165. #  ifndef I286
  166.     if (debug & 128) {
  167.     fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
  168.     fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
  169.     }
  170. #  else
  171.     if (debug & 128) {
  172.     fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
  173.     fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
  174.     }
  175. #  endif
  176. #endif
  177.     if (ptr != Nullch)
  178.     return ptr;
  179.     else {
  180.     fputs(nomem,stderr) FLUSH;
  181.     exit(1);
  182.     }
  183.     /*NOTREACHED*/
  184. #ifdef lint
  185.     return ptr;
  186. #endif
  187. }
  188.  
  189.  
  190. /* safe version of free */
  191.  
  192.  
  193. void
  194. safefree(where)
  195. char *where;
  196. {
  197. #ifdef DEBUGGING
  198. #  ifndef I286
  199.     if (debug & 128)
  200.     fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
  201. #  else
  202.     if (debug & 128)
  203.     fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
  204. #  endif
  205. #endif
  206.     if (where) {
  207.     /*SUPPRESS 701*/
  208.     free(where);
  209.     }
  210. }
  211.  
  212.  
  213. #endif /* !safemalloc */
  214.  
  215.  
  216. #ifdef LEAKTEST
  217.  
  218.  
  219. #define ALIGN sizeof(long)
  220.  
  221.  
  222. char *
  223. safexmalloc(x,size)
  224. int x;
  225. MEM_SIZE size;
  226. {
  227.     register char *where;
  228.  
  229.  
  230.     where = safemalloc(size + ALIGN);
  231.     xcount[x]++;
  232.     where[0] = x % 100;
  233.     where[1] = x / 100;
  234.     return where + ALIGN;
  235. }
  236.  
  237.  
  238. char *
  239. safexrealloc(where,size)
  240. char *where;
  241. MEM_SIZE size;
  242. {
  243.     return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
  244. }
  245.  
  246.  
  247. void
  248. safexfree(where)
  249. char *where;
  250. {
  251.     int x;
  252.  
  253.  
  254.     if (!where)
  255.     return;
  256.     where -= ALIGN;
  257.     x = where[0] + 100 * where[1];
  258.     xcount[x]--;
  259.     safefree(where);
  260. }
  261.  
  262.  
  263. xstat()
  264. {
  265.     register int i;
  266.  
  267.  
  268.     for (i = 0; i < MAXXCOUNT; i++) {
  269.     if (xcount[i] > lastxcount[i]) {
  270.         fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
  271.         lastxcount[i] = xcount[i];
  272.     }
  273.     }
  274. }
  275.  
  276.  
  277. #endif /* LEAKTEST */
  278.  
  279.  
  280. /* copy a string up to some (non-backslashed) delimiter, if any */
  281.  
  282.  
  283. char *
  284. cpytill(to,from,fromend,delim,retlen)
  285. register char *to;
  286. register char *from;
  287. register char *fromend;
  288. register int delim;
  289. int *retlen;
  290. {
  291.     char *origto = to;
  292.  
  293.  
  294.     for (; from < fromend; from++,to++) {
  295.     if (*from == '\\') {
  296.         if (from[1] == delim)
  297.         from++;
  298.         else if (from[1] == '\\')
  299.         *to++ = *from++;
  300.     }
  301.     else if (*from == delim)
  302.         break;
  303.     *to = *from;
  304.     }
  305.     *to = '\0';
  306.     *retlen = to - origto;
  307.     return from;
  308. }
  309.  
  310.  
  311. /* return ptr to little string in big string, NULL if not found */
  312. /* This routine was donated by Corey Satten. */
  313.  
  314.  
  315. char *
  316. instr(big, little)
  317. register char *big;
  318. register char *little;
  319. {
  320.     register char *s, *x;
  321.     register int first;
  322.  
  323.  
  324.     if (!little)
  325.     return big;
  326.     first = *little++;
  327.     if (!first)
  328.     return big;
  329.     while (*big) {
  330.     if (*big++ != first)
  331.         continue;
  332.     for (x=big,s=little; *s; /**/ ) {
  333.         if (!*x)
  334.         return Nullch;
  335.         if (*s++ != *x++) {
  336.         s--;
  337.         break;
  338.         }
  339.     }
  340.     if (!*s)
  341.         return big-1;
  342.     }
  343.     return Nullch;
  344. }
  345.  
  346.  
  347. /* same as instr but allow embedded nulls */
  348.  
  349.  
  350. char *
  351. ninstr(big, bigend, little, lend)
  352. register char *big;
  353. register char *bigend;
  354. char *little;
  355. char *lend;
  356. {
  357.     register char *s, *x;
  358.     register int first = *little;
  359.     register char *littleend = lend;
  360.  
  361.  
  362.     if (!first && little > littleend)
  363.     return big;
  364.     if (bigend - big < littleend - little)
  365.     return Nullch;
  366.     bigend -= littleend - little++;
  367.     while (big <= bigend) {
  368.     if (*big++ != first)
  369.         continue;
  370.     for (x=big,s=little; s < littleend; /**/ ) {
  371.         if (*s++ != *x++) {
  372.         s--;
  373.         break;
  374.         }
  375.     }
  376.     if (s >= littleend)
  377.         return big-1;
  378.     }
  379.     return Nullch;
  380. }
  381.  
  382.  
  383. /* reverse of the above--find last substring */
  384.  
  385.  
  386. char *
  387. rninstr(big, bigend, little, lend)
  388. register char *big;
  389. char *bigend;
  390. char *little;
  391. char *lend;
  392. {
  393.     register char *bigbeg;
  394.     register char *s, *x;
  395.     register int first = *little;
  396.     register char *littleend = lend;
  397.  
  398.  
  399.     if (!first && little > littleend)
  400.     return bigend;
  401.     bigbeg = big;
  402.     big = bigend - (littleend - little++);
  403.     while (big >= bigbeg) {
  404.     if (*big-- != first)
  405.         continue;
  406.     for (x=big+2,s=little; s < littleend; /**/ ) {
  407.         if (*s++ != *x++) {
  408.         s--;
  409.         break;
  410.         }
  411.     }
  412.     if (s >= littleend)
  413.         return big+1;
  414.     }
  415.     return Nullch;
  416. }
  417.  
  418.  
  419. unsigned char fold[] = {
  420.     0,    1,    2,    3,    4,    5,    6,    7,
  421.     8,    9,    10,    11,    12,    13,    14,    15,
  422.     16,    17,    18,    19,    20,    21,    22,    23,
  423.     24,    25,    26,    27,    28,    29,    30,    31,
  424.     32,    33,    34,    35,    36,    37,    38,    39,
  425.     40,    41,    42,    43,    44,    45,    46,    47,
  426.     48,    49,    50,    51,    52,    53,    54,    55,
  427.     56,    57,    58,    59,    60,    61,    62,    63,
  428.     64,    'a',    'b',    'c',    'd',    'e',    'f',    'g',
  429.     'h',    'i',    'j',    'k',    'l',    'm',    'n',    'o',
  430.     'p',    'q',    'r',    's',    't',    'u',    'v',    'w',
  431.     'x',    'y',    'z',    91,    92,    93,    94,    95,
  432.     96,    'A',    'B',    'C',    'D',    'E',    'F',    'G',
  433.     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
  434.     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
  435.     'X',    'Y',    'Z',    123,    124,    125,    126,    127,
  436.     128,    129,    130,    131,    132,    133,    134,    135,
  437.     136,    137,    138,    139,    140,    141,    142,    143,
  438.     144,    145,    146,    147,    148,    149,    150,    151,
  439.     152,    153,    154,    155,    156,    157,    158,    159,
  440.     160,    161,    162,    163,    164,    165,    166,    167,
  441.     168,    169,    170,    171,    172,    173,    174,    175,
  442.     176,    177,    178,    179,    180,    181,    182,    183,
  443.     184,    185,    186,    187,    188,    189,    190,    191,
  444.     192,    193,    194,    195,    196,    197,    198,    199,
  445.     200,    201,    202,    203,    204,    205,    206,    207,
  446.     208,    209,    210,    211,    212,    213,    214,    215,
  447.     216,    217,    218,    219,    220,    221,    222,    223,
  448.     224,    225,    226,    227,    228,    229,    230,    231,
  449.     232,    233,    234,    235,    236,    237,    238,    239,
  450.     240,    241,    242,    243,    244,    245,    246,    247,
  451.     248,    249,    250,    251,    252,    253,    254,    255
  452. };
  453.  
  454.  
  455. static unsigned char freq[] = {
  456.     1,    2,    84,    151,    154,    155,    156,    157,
  457.     165,    246,    250,    3,    158,    7,    18,    29,
  458.     40,    51,    62,    73,    85,    96,    107,    118,
  459.     129,    140,    147,    148,    149,    150,    152,    153,
  460.     255,    182,    224,    205,    174,    176,    180,    217,
  461.     233,    232,    236,    187,    235,    228,    234,    226,
  462.     222,    219,    211,    195,    188,    193,    185,    184,
  463.     191,    183,    201,    229,    181,    220,    194,    162,
  464.     163,    208,    186,    202,    200,    218,    198,    179,
  465.     178,    214,    166,    170,    207,    199,    209,    206,
  466.     204,    160,    212,    216,    215,    192,    175,    173,
  467.     243,    172,    161,    190,    203,    189,    164,    230,
  468.     167,    248,    227,    244,    242,    255,    241,    231,
  469.     240,    253,    169,    210,    245,    237,    249,    247,
  470.     239,    168,    252,    251,    254,    238,    223,    221,
  471.     213,    225,    177,    197,    171,    196,    159,    4,
  472.     5,    6,    8,    9,    10,    11,    12,    13,
  473.     14,    15,    16,    17,    19,    20,    21,    22,
  474.     23,    24,    25,    26,    27,    28,    30,    31,
  475.     32,    33,    34,    35,    36,    37,    38,    39,
  476.     41,    42,    43,    44,    45,    46,    47,    48,
  477.     49,    50,    52,    53,    54,    55,    56,    57,
  478.     58,    59,    60,    61,    63,    64,    65,    66,
  479.     67,    68,    69,    70,    71,    72,    74,    75,
  480.     76,    77,    78,    79,    80,    81,    82,    83,
  481.     86,    87,    88,    89,    90,    91,    92,    93,
  482.     94,    95,    97,    98,    99,    100,    101,    102,
  483.     103,    104,    105,    106,    108,    109,    110,    111,
  484.     112,    113,    114,    115,    116,    117,    119,    120,
  485.     121,    122,    123,    124,    125,    126,    127,    128,
  486.     130,    131,    132,    133,    134,    135,    136,    137,
  487.     138,    139,    141,    142,    143,    144,    145,    146
  488. };
  489.  
  490.  
  491. void
  492. fbmcompile(str, iflag)
  493. STR *str;
  494. int iflag;
  495. {
  496.     register unsigned char *s;
  497.     register unsigned char *table;
  498.     register unsigned int i;
  499.     register unsigned int len = str->str_cur;
  500.     int rarest = 0;
  501.     unsigned int frequency = 256;
  502.  
  503.  
  504.     Str_Grow(str,len+258);
  505. #ifndef lint
  506.     table = (unsigned char*)(str->str_ptr + len + 1);
  507. #else
  508.     table = Null(unsigned char*);
  509. #endif
  510.     s = table - 2;
  511.     for (i = 0; i < 256; i++) {
  512.     table[i] = len;
  513.     }
  514.     i = 0;
  515. #ifndef lint
  516.     while (s >= (unsigned char*)(str->str_ptr))
  517. #endif
  518.     {
  519.     if (table[*s] == len) {
  520. #ifndef pdp11
  521.         if (iflag)
  522.         table[*s] = table[fold[*s]] = i;
  523. #else
  524.         if (iflag) {
  525.         int j;
  526.         j = fold[*s];
  527.         table[j] = i;
  528.         table[*s] = i;
  529.         }
  530. #endif /* pdp11 */
  531.         else
  532.         table[*s] = i;
  533.     }
  534.     s--,i++;
  535.     }
  536.     str->str_pok |= SP_FBM;        /* deep magic */
  537.  
  538.  
  539. #ifndef lint
  540.     s = (unsigned char*)(str->str_ptr);        /* deeper magic */
  541. #else
  542.     s = Null(unsigned char*);
  543. #endif
  544.     if (iflag) {
  545.     register unsigned int tmp, foldtmp;
  546.     str->str_pok |= SP_CASEFOLD;
  547.     for (i = 0; i < len; i++) {
  548.         tmp=freq[s[i]];
  549.         foldtmp=freq[fold[s[i]]];
  550.         if (tmp < frequency && foldtmp < frequency) {
  551.         rarest = i;
  552.         /* choose most frequent among the two */
  553.         frequency = (tmp > foldtmp) ? tmp : foldtmp;
  554.         }
  555.     }
  556.     }
  557.     else {
  558.     for (i = 0; i < len; i++) {
  559.         if (freq[s[i]] < frequency) {
  560.         rarest = i;
  561.         frequency = freq[s[i]];
  562.         }
  563.     }
  564.     }
  565.     str->str_rare = s[rarest];
  566.     str->str_state = rarest;
  567. #ifdef DEBUGGING
  568.     if (debug & 512)
  569.     fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
  570. #endif
  571. }
  572.  
  573.  
  574. char *
  575. fbminstr(big, bigend, littlestr)
  576. unsigned char *big;
  577. register unsigned char *bigend;
  578. STR *littlestr;
  579. {
  580.     register unsigned char *s;
  581.     register int tmp;
  582.     register int littlelen;
  583.     register unsigned char *little;
  584.     register unsigned char *table;
  585.     register unsigned char *olds;
  586.     register unsigned char *oldlittle;
  587.  
  588.  
  589. #ifndef lint
  590.     if (!(littlestr->str_pok & SP_FBM)) {
  591.     if (!littlestr->str_ptr)
  592.         return (char*)big;
  593.     return ninstr((char*)big,(char*)bigend,
  594.         littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
  595.     }
  596. #endif
  597.  
  598.  
  599.     littlelen = littlestr->str_cur;
  600. #ifndef lint
  601.     if (littlestr->str_pok & SP_TAIL && !multiline) {    /* tail anchored? */
  602.     if (littlelen > bigend - big)
  603.         return Nullch;
  604.     little = (unsigned char*)littlestr->str_ptr;
  605.     if (littlestr->str_pok & SP_CASEFOLD) {    /* oops, fake it */
  606.         big = bigend - littlelen;        /* just start near end */
  607.         if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
  608.         big--;
  609.     }
  610.     else {
  611.         s = bigend - littlelen;
  612.         if (*s == *little && bcmp(s,little,littlelen)==0)
  613.         return (char*)s;        /* how sweet it is */
  614.         else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
  615.           && s > big) {
  616.             s--;
  617.         if (*s == *little && bcmp(s,little,littlelen)==0)
  618.             return (char*)s;
  619.         }
  620.         return Nullch;
  621.     }
  622.     }
  623.     table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
  624. #else
  625.     table = Null(unsigned char*);
  626. #endif
  627.     if (--littlelen >= bigend - big)
  628.     return Nullch;
  629.     s = big + littlelen;
  630.     oldlittle = little = table - 2;
  631.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insensitive? */
  632.     if (s < bigend) {
  633.       top1:
  634.         /*SUPPRESS 560*/
  635.         if (tmp = table[*s]) {
  636. #ifdef POINTERRIGOR
  637.         if (bigend - s > tmp) {
  638.             s += tmp;
  639.             goto top1;
  640.         }
  641. #else
  642.         if ((s += tmp) < bigend)
  643.             goto top1;
  644. #endif
  645.         return Nullch;
  646.         }
  647.         else {
  648.         tmp = littlelen;    /* less expensive than calling strncmp() */
  649.         olds = s;
  650.         while (tmp--) {
  651.             if (*--s == *--little || fold[*s] == *little)
  652.             continue;
  653.             s = olds + 1;    /* here we pay the price for failure */
  654.             little = oldlittle;
  655.             if (s < bigend)    /* fake up continue to outer loop */
  656.             goto top1;
  657.             return Nullch;
  658.         }
  659. #ifndef lint
  660.         return (char *)s;
  661. #endif
  662.         }
  663.     }
  664.     }
  665.     else {
  666.     if (s < bigend) {
  667.       top2:
  668.         /*SUPPRESS 560*/
  669.         if (tmp = table[*s]) {
  670. #ifdef POINTERRIGOR
  671.         if (bigend - s > tmp) {
  672.             s += tmp;
  673.             goto top2;
  674.         }
  675. #else
  676.         if ((s += tmp) < bigend)
  677.             goto top2;
  678. #endif
  679.         return Nullch;
  680.         }
  681.         else {
  682.         tmp = littlelen;    /* less expensive than calling strncmp() */
  683.         olds = s;
  684.         while (tmp--) {
  685.             if (*--s == *--little)
  686.             continue;
  687.             s = olds + 1;    /* here we pay the price for failure */
  688.             little = oldlittle;
  689.             if (s < bigend)    /* fake up continue to outer loop */
  690.             goto top2;
  691.             return Nullch;
  692.         }
  693. #ifndef lint
  694.         return (char *)s;
  695. #endif
  696.         }
  697.     }
  698.     }
  699.     return Nullch;
  700. }
  701.  
  702.  
  703. char *
  704. screaminstr(bigstr, littlestr)
  705. STR *bigstr;
  706. STR *littlestr;
  707. {
  708.     register unsigned char *s, *x;
  709.     register unsigned char *big;
  710.     register int pos;
  711.     register int previous;
  712.     register int first;
  713.     register unsigned char *little;
  714.     register unsigned char *bigend;
  715.     register unsigned char *littleend;
  716.  
  717.  
  718.     if ((pos = screamfirst[littlestr->str_rare]) < 0)
  719.     return Nullch;
  720. #ifndef lint
  721.     little = (unsigned char *)(littlestr->str_ptr);
  722. #else
  723.     little = Null(unsigned char *);
  724. #endif
  725.     littleend = little + littlestr->str_cur;
  726.     first = *little++;
  727.     previous = littlestr->str_state;
  728. #ifndef lint
  729.     big = (unsigned char *)(bigstr->str_ptr);
  730. #else
  731.     big = Null(unsigned char*);
  732. #endif
  733.     bigend = big + bigstr->str_cur;
  734.     while (pos < previous) {
  735. #ifndef lint
  736.     if (!(pos += screamnext[pos]))
  737. #endif
  738.         return Nullch;
  739.     }
  740. #ifdef POINTERRIGOR
  741.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  742.     do {
  743.         if (big[pos-previous] != first && big[pos-previous] != fold[first])
  744.         continue;
  745.         for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
  746.         if (x >= bigend)
  747.             return Nullch;
  748.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  749.             s--;
  750.             break;
  751.         }
  752.         }
  753.         if (s == littleend)
  754. #ifndef lint
  755.         return (char *)(big+pos-previous);
  756. #else
  757.         return Nullch;
  758. #endif
  759.     } while (
  760. #ifndef lint
  761.         pos += screamnext[pos]    /* does this goof up anywhere? */
  762. #else
  763.         pos += screamnext[0]
  764. #endif
  765.         );
  766.     }
  767.     else {
  768.     do {
  769.         if (big[pos-previous] != first)
  770.         continue;
  771.         for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
  772.         if (x >= bigend)
  773.             return Nullch;
  774.         if (*s++ != *x++) {
  775.             s--;
  776.             break;
  777.         }
  778.         }
  779.         if (s == littleend)
  780. #ifndef lint
  781.         return (char *)(big+pos-previous);
  782. #else
  783.         return Nullch;
  784. #endif
  785.     } while (
  786. #ifndef lint
  787.         pos += screamnext[pos]
  788. #else
  789.         pos += screamnext[0]
  790. #endif
  791.         );
  792.     }
  793. #else /* !POINTERRIGOR */
  794.     big -= previous;
  795.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  796.     do {
  797.         if (big[pos] != first && big[pos] != fold[first])
  798.         continue;
  799.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  800.         if (x >= bigend)
  801.             return Nullch;
  802.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  803.             s--;
  804.             break;
  805.         }
  806.         }
  807.         if (s == littleend)
  808. #ifndef lint
  809.         return (char *)(big+pos);
  810. #else
  811.         return Nullch;
  812. #endif
  813.     } while (
  814. #ifndef lint
  815.         pos += screamnext[pos]    /* does this goof up anywhere? */
  816. #else
  817.         pos += screamnext[0]
  818. #endif
  819.         );
  820.     }
  821.     else {
  822.     do {
  823.         if (big[pos] != first)
  824.         continue;
  825.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  826.         if (x >= bigend)
  827.             return Nullch;
  828.         if (*s++ != *x++) {
  829.             s--;
  830.             break;
  831.         }
  832.         }
  833.         if (s == littleend)
  834. #ifndef lint
  835.         return (char *)(big+pos);
  836. #else
  837.         return Nullch;
  838. #endif
  839.     } while (
  840. #ifndef lint
  841.         pos += screamnext[pos]
  842. #else
  843.         pos += screamnext[0]
  844. #endif
  845.         );
  846.     }
  847. #endif /* POINTERRIGOR */
  848.     return Nullch;
  849. }
  850.  
  851.  
  852. /* copy a string to a safe spot */
  853.  
  854.  
  855. char *
  856. savestr(str)
  857. char *str;
  858. {
  859.     register char *newaddr;
  860.  
  861.  
  862.     New(902,newaddr,strlen(str)+1,char);
  863.     (void)strcpy(newaddr,str);
  864.     return newaddr;
  865. }
  866.  
  867.  
  868. /* same thing but with a known length */
  869.  
  870.  
  871. char *
  872. nsavestr(str, len)
  873. char *str;
  874. register int len;
  875. {
  876.     register char *newaddr;
  877.  
  878.  
  879.     New(903,newaddr,len+1,char);
  880.     (void)bcopy(str,newaddr,len);    /* might not be null terminated */
  881.     newaddr[len] = '\0';        /* is now */
  882.     return newaddr;
  883. }
  884.  
  885.  
  886. /* grow a static string to at least a certain length */
  887.  
  888.  
  889. void
  890. growstr(strptr,curlen,newlen)
  891. char **strptr;
  892. int *curlen;
  893. int newlen;
  894. {
  895.     if (newlen > *curlen) {        /* need more room? */
  896.     if (*curlen)
  897.         Renew(*strptr,newlen,char);
  898.     else
  899.         New(905,*strptr,newlen,char);
  900.     *curlen = newlen;
  901.     }
  902. }
  903.  
  904.  
  905. #ifndef I_VARARGS
  906. /*VARARGS1*/
  907. mess(pat,a1,a2,a3,a4)
  908. char *pat;
  909. long a1, a2, a3, a4;
  910. {
  911.     char *s;
  912.     int usermess = strEQ(pat,"%s");
  913.     STR *tmpstr;
  914.  
  915.  
  916.     s = buf;
  917.     if (usermess) {
  918.     tmpstr = str_mortal(&str_undef);
  919.     str_set(tmpstr, (char*)a1);
  920.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  921.     }
  922.     else {
  923.     (void)sprintf(s,pat,a1,a2,a3,a4);
  924.     s += strlen(s);
  925.     }
  926.  
  927.  
  928.     if (s[-1] != '\n') {
  929.     if (curcmd->c_line) {
  930.         (void)sprintf(s," at %s line %ld",
  931.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  932.         s += strlen(s);
  933.     }
  934.     if (last_in_stab &&
  935.         stab_io(last_in_stab) &&
  936.         stab_io(last_in_stab)->lines ) {
  937.         (void)sprintf(s,", <%s> line %ld",
  938.           last_in_stab == argvstab ? "" : stab_name(last_in_stab),
  939.           (long)stab_io(last_in_stab)->lines);
  940.         s += strlen(s);
  941.     }
  942.     (void)strcpy(s,".\n");
  943.     if (usermess)
  944.         str_cat(tmpstr,buf+1);
  945.     }
  946.     if (usermess)
  947.     return tmpstr->str_ptr;
  948.     else
  949.     return buf;
  950. }
  951.  
  952.  
  953. /*VARARGS1*/
  954. fatal(pat,a1,a2,a3,a4)
  955. char *pat;
  956. long a1, a2, a3, a4;
  957. {
  958.     extern FILE *e_fp;
  959.     extern char *e_tmpname;
  960.     char *tmps;
  961.     char *message;
  962.  
  963.  
  964.     message = mess(pat,a1,a2,a3,a4);
  965.     if (in_eval) {
  966.     str_set(stab_val(stabent("@",TRUE)),message);
  967.     tmps = "_EVAL_";
  968.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  969.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  970. #ifdef DEBUGGING
  971.         if (debug & 4) {
  972.         deb("(Skipping label #%d %s)\n",loop_ptr,
  973.             loop_stack[loop_ptr].loop_label);
  974.         }
  975. #endif
  976.         loop_ptr--;
  977.     }
  978. #ifdef DEBUGGING
  979.     if (debug & 4) {
  980.         deb("(Found label #%d %s)\n",loop_ptr,
  981.         loop_stack[loop_ptr].loop_label);
  982.     }
  983. #endif
  984.     if (loop_ptr < 0) {
  985.         in_eval = 0;
  986.         fatal("Bad label: %s", tmps);
  987.     }
  988.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  989.     }
  990.     fputs(message,stderr);
  991.     (void)fflush(stderr);
  992.     if (e_fp)
  993.     (void)UNLINK(e_tmpname);
  994.     statusvalue >>= 8;
  995.     exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
  996. }
  997.  
  998.  
  999. /*VARARGS1*/
  1000. warn(pat,a1,a2,a3,a4)
  1001. char *pat;
  1002. long a1, a2, a3, a4;
  1003. {
  1004.     char *message;
  1005.  
  1006.  
  1007.     message = mess(pat,a1,a2,a3,a4);
  1008.     fputs(message,stderr);
  1009. #ifdef LEAKTEST
  1010. #ifdef DEBUGGING
  1011.     if (debug & 4096)
  1012.     xstat();
  1013. #endif
  1014. #endif
  1015.     (void)fflush(stderr);
  1016. }
  1017. #else
  1018. /*VARARGS0*/
  1019. char *
  1020. mess(args)
  1021. va_list args;
  1022. {
  1023.     char *pat;
  1024.     char *s;
  1025.     STR *tmpstr;
  1026.     int usermess;
  1027. #ifndef HAS_VPRINTF
  1028. #ifdef CHARVSPRINTF
  1029.     char *vsprintf();
  1030. #else
  1031.     int vsprintf();
  1032. #endif
  1033. #endif
  1034.  
  1035.  
  1036. #ifdef lint
  1037.     pat = Nullch;
  1038. #else
  1039.     pat = va_arg(args, char *);
  1040. #endif
  1041.     s = buf;
  1042.     usermess = strEQ(pat, "%s");
  1043.     if (usermess) {
  1044.     tmpstr = str_mortal(&str_undef);
  1045.     str_set(tmpstr, va_arg(args, char *));
  1046.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  1047.     }
  1048.     else {
  1049.     (void) vsprintf(s,pat,args);
  1050.     s += strlen(s);
  1051.     }
  1052.  
  1053.  
  1054.     if (s[-1] != '\n') {
  1055.     if (curcmd->c_line) {
  1056.         (void)sprintf(s," at %s line %ld",
  1057.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  1058.         s += strlen(s);
  1059.     }
  1060.     if (last_in_stab &&
  1061.         stab_io(last_in_stab) &&
  1062.         stab_io(last_in_stab)->lines ) {
  1063.         (void)sprintf(s,", <%s> line %ld",
  1064.           last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
  1065.           (long)stab_io(last_in_stab)->lines);
  1066.         s += strlen(s);
  1067.     }
  1068.     (void)strcpy(s,".\n");
  1069.     if (usermess)
  1070.         str_cat(tmpstr,buf+1);
  1071.     }
  1072.  
  1073.  
  1074.     if (usermess)
  1075.     return tmpstr->str_ptr;
  1076.     else
  1077.     return buf;
  1078. }
  1079.  
  1080.  
  1081. /*VARARGS0*/
  1082. fatal(va_alist)
  1083. va_dcl
  1084. {
  1085.     va_list args;
  1086.     extern FILE *e_fp;
  1087.     extern char *e_tmpname;
  1088.     char *tmps;
  1089.     char *message;
  1090.  
  1091.  
  1092. #ifndef lint
  1093.     va_start(args);
  1094. #else
  1095.     args = 0;
  1096. #endif
  1097.     message = mess(args);
  1098.     va_end(args);
  1099.     if (in_eval) {
  1100.     str_set(stab_val(stabent("@",TRUE)),message);
  1101.     tmps = "_EVAL_";
  1102.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  1103.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  1104. #ifdef DEBUGGING
  1105.         if (debug & 4) {
  1106.         deb("(Skipping label #%d %s)\n",loop_ptr,
  1107.             loop_stack[loop_ptr].loop_label);
  1108.         }
  1109. #endif
  1110.         loop_ptr--;
  1111.     }
  1112. #ifdef DEBUGGING
  1113.     if (debug & 4) {
  1114.         deb("(Found label #%d %s)\n",loop_ptr,
  1115.         loop_stack[loop_ptr].loop_label);
  1116.     }
  1117. #endif
  1118.     if (loop_ptr < 0) {
  1119.         in_eval = 0;
  1120.         fatal("Bad label: %s", tmps);
  1121.     }
  1122.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  1123.     }
  1124.     fputs(message,stderr);
  1125.     (void)fflush(stderr);
  1126.     if (e_fp)
  1127.     (void)UNLINK(e_tmpname);
  1128.     statusvalue >>= 8;
  1129.     exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
  1130. }
  1131.  
  1132.  
  1133. /*VARARGS0*/
  1134. warn(va_alist)
  1135. va_dcl
  1136. {
  1137.     va_list args;
  1138.     char *message;
  1139.  
  1140.  
  1141. #ifndef lint
  1142.     va_start(args);
  1143. #else
  1144.     args = 0;
  1145. #endif
  1146.     message = mess(args);
  1147.     va_end(args);
  1148.  
  1149.  
  1150.     fputs(message,stderr);
  1151. #ifdef LEAKTEST
  1152. #ifdef DEBUGGING
  1153.     if (debug & 4096)
  1154.     xstat();
  1155. #endif
  1156. #endif
  1157.     (void)fflush(stderr);
  1158. }
  1159. #endif
  1160.  
  1161.  
  1162. void
  1163. setenv(nam,val)
  1164. char *nam, *val;
  1165. {
  1166.     register int i=envix(nam);        /* where does it go? */
  1167.  
  1168.  
  1169.     if (environ == origenviron) {    /* need we copy environment? */
  1170.     int j;
  1171.     int max;
  1172.     char **tmpenv;
  1173.  
  1174.  
  1175.     /*SUPPRESS 530*/
  1176.     for (max = i; environ[max]; max++) ;
  1177.     New(901,tmpenv, max+2, char*);
  1178.     for (j=0; j<max; j++)        /* copy environment */
  1179.         tmpenv[j] = savestr(environ[j]);
  1180.     tmpenv[max] = Nullch;
  1181.     environ = tmpenv;        /* tell exec where it is now */
  1182.     }
  1183.     if (!val) {
  1184.     while (environ[i]) {
  1185.         environ[i] = environ[i+1];
  1186.         i++;
  1187.     }
  1188.     return;
  1189.     }
  1190.     if (!environ[i]) {            /* does not exist yet */
  1191.     Renew(environ, i+2, char*);    /* just expand it a bit */
  1192.     environ[i+1] = Nullch;    /* make sure it's null terminated */
  1193.     }
  1194.     else
  1195.     Safefree(environ[i]);
  1196.     New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
  1197. #ifndef MSDOS
  1198.     (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
  1199. #else
  1200.     /* MS-DOS requires environment variable names to be in uppercase */
  1201.     /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
  1202.      * some utilities and applications may break because they only look
  1203.      * for upper case strings. (Fixed strupr() bug here.)]
  1204.      */
  1205.     strcpy(environ[i],nam); strupr(environ[i]);
  1206.     (void)sprintf(environ[i] + strlen(nam),"=%s",val);
  1207. #endif /* MSDOS */
  1208. }
  1209.  
  1210.  
  1211. int
  1212. envix(nam)
  1213. char *nam;
  1214. {
  1215.     register int i, len = strlen(nam);
  1216.  
  1217.  
  1218.     for (i = 0; environ[i]; i++) {
  1219.     if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
  1220.         break;            /* strnEQ must come first to avoid */
  1221.     }                    /* potential SEGV's */
  1222.     return i;
  1223. }
  1224.  
  1225.  
  1226. #ifdef EUNICE
  1227. unlnk(f)    /* unlink all versions of a file */
  1228. char *f;
  1229. {
  1230.     int i;
  1231.  
  1232.  
  1233.     for (i = 0; unlink(f) >= 0; i++) ;
  1234.     return i ? 0 : -1;
  1235. }
  1236. #endif
  1237.  
  1238.  
  1239. #ifndef HAS_MEMCPY
  1240. #ifndef HAS_BCOPY
  1241. char *
  1242. bcopy(from,to,len)
  1243. register char *from;
  1244. register char *to;
  1245. register int len;
  1246. {
  1247.     char *retval = to;
  1248.  
  1249.  
  1250.     while (len--)
  1251.     *to++ = *from++;
  1252.     return retval;
  1253. }
  1254. #endif
  1255.  
  1256.  
  1257. #ifndef HAS_BZERO
  1258. char *
  1259. bzero(loc,len)
  1260. register char *loc;
  1261. register int len;
  1262. {
  1263.     char *retval = loc;
  1264.  
  1265.  
  1266.     while (len--)
  1267.     *loc++ = 0;
  1268.     return retval;
  1269. }
  1270. #endif
  1271. #endif
  1272.  
  1273.  
  1274. #ifdef I_VARARGS
  1275. #ifndef HAS_VPRINTF
  1276.  
  1277.  
  1278. #ifdef CHARVSPRINTF
  1279. char *
  1280. #else
  1281. int
  1282. #endif
  1283. vsprintf(dest, pat, args)
  1284. char *dest, *pat, *args;
  1285. {
  1286.     FILE fakebuf;
  1287.  
  1288.  
  1289.     fakebuf._ptr = dest;
  1290.     fakebuf._cnt = 32767;
  1291. #ifndef _IOSTRG
  1292. #define _IOSTRG 0
  1293. #endif
  1294.     fakebuf._flag = _IOWRT|_IOSTRG;
  1295.     _doprnt(pat, args, &fakebuf);    /* what a kludge */
  1296.     (void)putc('\0', &fakebuf);
  1297. #ifdef CHARVSPRINTF
  1298.     return(dest);
  1299. #else
  1300.     return 0;        /* perl doesn't use return value */
  1301. #endif
  1302. }
  1303.  
  1304.  
  1305. #ifdef DEBUGGING
  1306. int
  1307. vfprintf(fd, pat, args)
  1308. FILE *fd;
  1309. char *pat, *args;
  1310. {
  1311.     _doprnt(pat, args, fd);
  1312.     return 0;        /* wrong, but perl doesn't use the return value */
  1313. }
  1314. #endif
  1315. #endif /* HAS_VPRINTF */
  1316. #endif /* I_VARARGS */
  1317.  
  1318.  
  1319. /*
  1320.  * I think my_swap(), htonl() and ntohl() have never been used.
  1321.  * perl.h contains last-chance references to my_swap(), my_htonl()
  1322.  * and my_ntohl().  I presume these are the intended functions;
  1323.  * but htonl() and ntohl() have the wrong names.  There are no
  1324.  * functions my_htonl() and my_ntohl() defined anywhere.
  1325.  * -DWS
  1326.  */
  1327. #ifdef MYSWAP
  1328. #if BYTEORDER != 0x4321
  1329. short
  1330. my_swap(s)
  1331. short s;
  1332. {
  1333. #if (BYTEORDER & 1) == 0
  1334.     short result;
  1335.  
  1336.  
  1337.     result = ((s & 255) << 8) + ((s >> 8) & 255);
  1338.     return result;
  1339. #else
  1340.     return s;
  1341. #endif
  1342. }
  1343.  
  1344.  
  1345. long
  1346. htonl(l)
  1347. register long l;
  1348. {
  1349.     union {
  1350.     long result;
  1351.     char c[sizeof(long)];
  1352.     } u;
  1353.  
  1354.  
  1355. #if BYTEORDER == 0x1234
  1356.     u.c[0] = (l >> 24) & 255;
  1357.     u.c[1] = (l >> 16) & 255;
  1358.     u.c[2] = (l >> 8) & 255;
  1359.     u.c[3] = l & 255;
  1360.     return u.result;
  1361. #else
  1362. #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
  1363.     fatal("Unknown BYTEORDER\n");
  1364. #else
  1365.     register int o;
  1366.     register int s;
  1367.  
  1368.  
  1369.     for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
  1370.     u.c[o & 0xf] = (l >> s) & 255;
  1371.     }
  1372.     return u.result;
  1373. #endif
  1374. #endif
  1375. }
  1376.  
  1377.  
  1378. long
  1379. ntohl(l)
  1380. register long l;
  1381. {
  1382.     union {
  1383.     long l;
  1384.     char c[sizeof(long)];
  1385.     } u;
  1386.  
  1387.  
  1388. #if BYTEORDER == 0x1234
  1389.     u.c[0] = (l >> 24) & 255;
  1390.     u.c[1] = (l >> 16) & 255;
  1391.     u.c[2] = (l >> 8) & 255;
  1392.     u.c[3] = l & 255;
  1393.     return u.l;
  1394. #else
  1395. #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
  1396.     fatal("Unknown BYTEORDER\n");
  1397. #else
  1398.     register int o;
  1399.     register int s;
  1400.  
  1401.  
  1402.     u.l = l;
  1403.     l = 0;
  1404.     for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
  1405.     l |= (u.c[o & 0xf] & 255) << s;
  1406.     }
  1407.     return l;
  1408. #endif
  1409. #endif
  1410. }
  1411.  
  1412.  
  1413. #endif /* BYTEORDER != 0x4321 */
  1414. #endif /* MYSWAP */
  1415.  
  1416.  
  1417. /*
  1418.  * Little-endian byte order functions - 'v' for 'VAX', or 'reVerse'.
  1419.  * If these functions are defined,
  1420.  * the BYTEORDER is neither 0x1234 nor 0x4321.
  1421.  * However, this is not assumed.
  1422.  * -DWS
  1423.  */
  1424.  
  1425.  
  1426. #define HTOV(name,type)                        \
  1427.     type                            \
  1428.     name (n)                        \
  1429.     register type n;                    \
  1430.     {                            \
  1431.         union {                        \
  1432.         type value;                    \
  1433.         char c[sizeof(type)];                \
  1434.         } u;                        \
  1435.         register int i;                    \
  1436.         register int s;                    \
  1437.         for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) {    \
  1438.         u.c[i] = (n >> s) & 0xFF;            \
  1439.         }                            \
  1440.         return u.value;                    \
  1441.     }
  1442.  
  1443.  
  1444. #define VTOH(name,type)                        \
  1445.     type                            \
  1446.     name (n)                        \
  1447.     register type n;                    \
  1448.     {                            \
  1449.         union {                        \
  1450.         type value;                    \
  1451.         char c[sizeof(type)];                \
  1452.         } u;                        \
  1453.         register int i;                    \
  1454.         register int s;                    \
  1455.         u.value = n;                    \
  1456.         n = 0;                        \
  1457.         for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) {    \
  1458.         n += (u.c[i] & 0xFF) << s;            \
  1459.         }                            \
  1460.         return n;                        \
  1461.     }
  1462.  
  1463.  
  1464. #if defined(HAS_HTOVS) && !defined(htovs)
  1465. HTOV(htovs,short)
  1466. #endif
  1467. #if defined(HAS_HTOVL) && !defined(htovl)
  1468. HTOV(htovl,long)
  1469. #endif
  1470. #if defined(HAS_VTOHS) && !defined(vtohs)
  1471. VTOH(vtohs,short)
  1472. #endif
  1473. #if defined(HAS_VTOHL) && !defined(vtohl)
  1474. VTOH(vtohl,long)
  1475. #endif
  1476.  
  1477.  
  1478. #ifndef MSDOS
  1479. FILE *
  1480. mypopen(cmd,mode)
  1481. char    *cmd;
  1482. char    *mode;
  1483. {
  1484.     int p[2];
  1485.     register int this, that;
  1486.     register int pid;
  1487.     STR *str;
  1488.     int doexec = strNE(cmd,"-");
  1489.  
  1490.  
  1491.     if (pipe(p) < 0)
  1492.     return Nullfp;
  1493.     this = (*mode == 'w');
  1494.     that = !this;
  1495. #ifdef TAINT
  1496.     if (doexec) {
  1497.     taintenv();
  1498.     taintproper("Insecure dependency in exec");
  1499.     }
  1500. #endif
  1501.     while ((pid = (doexec?vfork():fork())) < 0) {
  1502.     if (errno != EAGAIN) {
  1503.         close(p[this]);
  1504.         if (!doexec)
  1505.         fatal("Can't fork");
  1506.         return Nullfp;
  1507.     }
  1508.     sleep(5);
  1509.     }
  1510.     if (pid == 0) {
  1511. #define THIS that
  1512. #define THAT this
  1513.     close(p[THAT]);
  1514.     if (p[THIS] != (*mode == 'r')) {
  1515.         dup2(p[THIS], *mode == 'r');
  1516.         close(p[THIS]);
  1517.     }
  1518.     if (doexec) {
  1519. #if !defined(HAS_FCNTL) || !defined(F_SETFD)
  1520.         int fd;
  1521.  
  1522.  
  1523. #ifndef NOFILE
  1524. #define NOFILE 20
  1525. #endif
  1526.         for (fd = maxsysfd + 1; fd < NOFILE; fd++)
  1527.         close(fd);
  1528. #endif
  1529.         do_exec(cmd);    /* may or may not use the shell */
  1530.         warn("Can't exec \"%s\": %s", cmd, strerror(errno));
  1531.         _exit(1);
  1532.     }
  1533.     /*SUPPRESS 560*/
  1534.     if (tmpstab = stabent("$",allstabs))
  1535.         str_numset(STAB_STR(tmpstab),(double)getpid());
  1536.     forkprocess = 0;
  1537.     hclear(pidstatus, FALSE);    /* we have no children */
  1538.     return Nullfp;
  1539. #undef THIS
  1540. #undef THAT
  1541.     }
  1542.     do_execfree();    /* free any memory malloced by child on vfork */
  1543.     close(p[that]);
  1544.     if (p[that] < p[this]) {
  1545.     dup2(p[this], p[that]);
  1546.     close(p[this]);
  1547.     p[this] = p[that];
  1548.     }
  1549.     str = afetch(fdpid,p[this],TRUE);
  1550.     str->str_u.str_useful = pid;
  1551.     forkprocess = pid;
  1552.     return fdopen(p[this], mode);
  1553. }
  1554. #endif /* !MSDOS */
  1555.  
  1556.  
  1557. #ifdef NOTDEF
  1558. dumpfds(s)
  1559. char *s;
  1560. {
  1561.     int fd;
  1562.     struct stat tmpstatbuf;
  1563.  
  1564.  
  1565.     fprintf(stderr,"%s", s);
  1566.     for (fd = 0; fd < 32; fd++) {
  1567.     if (fstat(fd,&tmpstatbuf) >= 0)
  1568.         fprintf(stderr," %d",fd);
  1569.     }
  1570.     fprintf(stderr,"\n");
  1571. }
  1572. #endif
  1573.  
  1574.  
  1575. #ifndef HAS_DUP2
  1576. dup2(oldfd,newfd)
  1577. int oldfd;
  1578. int newfd;
  1579. {
  1580. #if defined(HAS_FCNTL) && defined(F_DUPFD)
  1581.     close(newfd);
  1582.     fcntl(oldfd, F_DUPFD, newfd);
  1583. #else
  1584.     int fdtmp[256];
  1585.     int fdx = 0;
  1586.     int fd;
  1587.  
  1588.  
  1589.     if (oldfd == newfd)
  1590.     return 0;
  1591.     close(newfd);
  1592.     while ((fd = dup(oldfd)) != newfd)    /* good enough for low fd's */
  1593.     fdtmp[fdx++] = fd;
  1594.     while (fdx > 0)
  1595.     close(fdtmp[--fdx]);
  1596. #endif
  1597. }
  1598. #endif
  1599.  
  1600.  
  1601. #ifndef MSDOS
  1602. int
  1603. mypclose(ptr)
  1604. FILE *ptr;
  1605. {
  1606. #ifdef VOIDSIG
  1607.     void (*hstat)(), (*istat)(), (*qstat)();
  1608. #else
  1609.     int (*hstat)(), (*istat)(), (*qstat)();
  1610. #endif
  1611.     int status;
  1612.     STR *str;
  1613.     int pid;
  1614.  
  1615.  
  1616.     str = afetch(fdpid,fileno(ptr),TRUE);
  1617.     pid = (int)str->str_u.str_useful;
  1618.     astore(fdpid,fileno(ptr),Nullstr);
  1619.     fclose(ptr);
  1620.     hstat = signal(SIGHUP, SIG_IGN);
  1621.     istat = signal(SIGINT, SIG_IGN);
  1622.     qstat = signal(SIGQUIT, SIG_IGN);
  1623.     pid = wait4pid(pid, &status, 0);
  1624.     signal(SIGHUP, hstat);
  1625.     signal(SIGINT, istat);
  1626.     signal(SIGQUIT, qstat);
  1627.     return(pid < 0 ? pid : status);
  1628. }
  1629.  
  1630.  
  1631. int
  1632. wait4pid(pid,statusp,flags)
  1633. int pid;
  1634. int *statusp;
  1635. int flags;
  1636. {
  1637. #if !defined(HAS_WAIT4) && !defined(HAS_WAITPID)
  1638.     int result;
  1639.     STR *str;
  1640.     char spid[16];
  1641. #endif
  1642.  
  1643.  
  1644.     if (!pid)
  1645.     return -1;
  1646. #ifdef HAS_WAIT4
  1647.     return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
  1648. #else
  1649. #ifdef HAS_WAITPID
  1650.     return waitpid(pid,statusp,flags);
  1651. #else
  1652.     if (pid > 0) {
  1653.     sprintf(spid, "%d", pid);
  1654.     str = hfetch(pidstatus,spid,strlen(spid),FALSE);
  1655.     if (str != &str_undef) {
  1656.         *statusp = (int)str->str_u.str_useful;
  1657.         hdelete(pidstatus,spid,strlen(spid));
  1658.         return pid;
  1659.     }
  1660.     }
  1661.     else {
  1662.     HENT *entry;
  1663.  
  1664.  
  1665.     hiterinit(pidstatus);
  1666.     if (entry = hiternext(pidstatus)) {
  1667.         pid = atoi(hiterkey(entry,statusp));
  1668.         str = hiterval(entry);
  1669.         *statusp = (int)str->str_u.str_useful;
  1670.         sprintf(spid, "%d", pid);
  1671.         hdelete(pidstatus,spid,strlen(spid));
  1672.         return pid;
  1673.     }
  1674.     }
  1675.     if (flags)
  1676.     fatal("Can't do waitpid with flags");
  1677.     else {
  1678.     while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
  1679.         pidgone(result,*statusp);
  1680.     if (result < 0)
  1681.         *statusp = -1;
  1682.     }
  1683.     return result;
  1684. #endif
  1685. #endif
  1686. }
  1687.  
  1688.  
  1689. /*SUPPRESS 590*/
  1690. pidgone(pid,status)
  1691. int pid;
  1692. int status;
  1693. {
  1694. #if defined(HAS_WAIT4) || defined(HAS_WAITPID)
  1695. #else
  1696.     register STR *str;
  1697.     char spid[16];
  1698.  
  1699.  
  1700.     sprintf(spid, "%d", pid);
  1701.     str = hfetch(pidstatus,spid,strlen(spid),TRUE);
  1702.     str->str_u.str_useful = status;
  1703. #endif
  1704.     return;
  1705. }
  1706. #endif /* !MSDOS */
  1707.  
  1708.  
  1709. #ifndef HAS_MEMCMP
  1710. memcmp(s1,s2,len)
  1711. register unsigned char *s1;
  1712. register unsigned char *s2;
  1713. register int len;
  1714. {
  1715.     register int tmp;
  1716.  
  1717.  
  1718.     while (len--) {
  1719.     if (tmp = *s1++ - *s2++)
  1720.         return tmp;
  1721.     }
  1722.     return 0;
  1723. }
  1724. #endif /* HAS_MEMCMP */
  1725.  
  1726.  
  1727. void
  1728. repeatcpy(to,from,len,count)
  1729. register char *to;
  1730. register char *from;
  1731. int len;
  1732. register int count;
  1733. {
  1734.     register int todo;
  1735.     register char *frombase = from;
  1736.  
  1737.  
  1738.     if (len == 1) {
  1739.     todo = *from;
  1740.     while (count-- > 0)
  1741.         *to++ = todo;
  1742.     return;
  1743.     }
  1744.     while (count-- > 0) {
  1745.     for (todo = len; todo > 0; todo--) {
  1746.         *to++ = *from++;
  1747.     }
  1748.     from = frombase;
  1749.     }
  1750. }
  1751.  
  1752.  
  1753. #ifndef CASTNEGFLOAT
  1754. unsigned long
  1755. castulong(f)
  1756. double f;
  1757. {
  1758.     long along;
  1759.  
  1760.  
  1761. #if CASTFLAGS & 2
  1762. #   define BIGDOUBLE 2147483648.0
  1763.     if (f >= BIGDOUBLE)
  1764.     return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
  1765. #endif
  1766.     if (f >= 0.0)
  1767.     return (unsigned long)f;
  1768.     along = (long)f;
  1769.     return (unsigned long)along;
  1770. }
  1771. #endif
  1772.  
  1773.  
  1774. #ifndef HAS_RENAME
  1775. int
  1776. same_dirent(a,b)
  1777. char *a;
  1778. char *b;
  1779. {
  1780.     char *fa = rindex(a,'/');
  1781.     char *fb = rindex(b,'/');
  1782.     struct stat tmpstatbuf1;
  1783.     struct stat tmpstatbuf2;
  1784. #ifndef MAXPATHLEN
  1785. #define MAXPATHLEN 1024
  1786. #endif
  1787.     char tmpbuf[MAXPATHLEN+1];
  1788.  
  1789.  
  1790.     if (fa)
  1791.     fa++;
  1792.     else
  1793.     fa = a;
  1794.     if (fb)
  1795.     fb++;
  1796.     else
  1797.     fb = b;
  1798.     if (strNE(a,b))
  1799.     return FALSE;
  1800.     if (fa == a)
  1801.     strcpy(tmpbuf,".");
  1802.     else
  1803.     strncpy(tmpbuf, a, fa - a);
  1804.     if (stat(tmpbuf, &tmpstatbuf1) < 0)
  1805.     return FALSE;
  1806.     if (fb == b)
  1807.     strcpy(tmpbuf,".");
  1808.     else
  1809.     strncpy(tmpbuf, b, fb - b);
  1810.     if (stat(tmpbuf, &tmpstatbuf2) < 0)
  1811.     return FALSE;
  1812.     return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
  1813.        tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
  1814. }
  1815. #endif /* !HAS_RENAME */
  1816.  
  1817.  
  1818. unsigned long
  1819. scanoct(start, len, retlen)
  1820. char *start;
  1821. int len;
  1822. int *retlen;
  1823. {
  1824.     register char *s = start;
  1825.     register unsigned long retval = 0;
  1826.  
  1827.  
  1828.     while (len-- && *s >= '0' && *s <= '7') {
  1829.     retval <<= 3;
  1830.     retval |= *s++ - '0';
  1831.     }
  1832.     *retlen = s - start;
  1833.     return retval;
  1834. }
  1835.  
  1836.  
  1837. unsigned long
  1838. scanhex(start, len, retlen)
  1839. char *start;
  1840. int len;
  1841. int *retlen;
  1842. {
  1843.     register char *s = start;
  1844.     register unsigned long retval = 0;
  1845.     char *tmp;
  1846.  
  1847.  
  1848.     while (len-- && *s && (tmp = index(hexdigit, *s))) {
  1849.     retval <<= 4;
  1850.     retval |= (tmp - hexdigit) & 15;
  1851.     s++;
  1852.     }
  1853.     *retlen = s - start;
  1854.     return retval;
  1855. }
  1856.